package com.example.demo.service.impl;

import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.lang.Assert;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.StrUtil;
import com.example.demo.common.constant.SystemConstants;
import com.example.demo.common.enums.StatusEnum;
import com.example.demo.mapper.SysPermissionMapper;
import com.example.demo.mapper.SysRoleMapper;
import com.example.demo.mapper.SysRolePermissionMapper;
import com.example.demo.model.converter.SysRoleConverter;
import com.example.demo.model.core.PageVo;
import com.example.demo.model.entity.SysPermission;
import com.example.demo.model.entity.SysRole;
import com.example.demo.model.entity.SysRolePermission;
import com.example.demo.model.enums.MenuTypeEnum;
import com.example.demo.model.form.RoleForm;
import com.example.demo.model.form.RolePermForm;
import com.example.demo.model.query.RoleQuery;
import com.example.demo.model.vo.OptionVO;
import com.example.demo.model.vo.RoleVO;
import com.example.demo.model.vo.RouteVO;
import com.example.demo.service.SysRoleService;
import com.fasterxml.jackson.core.type.TypeReference;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.mybatisflex.core.paginate.Page;
import com.mybatisflex.core.query.QueryWrapper;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.*;
import java.util.stream.Collectors;

@Service
public class SysRoleServiceImpl implements SysRoleService {

    @Autowired
    private SysRoleConverter sysRoleConverter;
    @Autowired
    private SysRoleMapper sysRoleMapper;
    @Autowired
    private SysRolePermissionMapper sysRolePermissionMapper;
    @Autowired
    private SysPermissionMapper sysPermissionMapper;

    @Override
    @Transactional
    public void add(RoleForm form) {
        Assert.isTrue(sysRoleMapper.selectCountByQuery(QueryWrapper.create().eq("name", form.getName())) == 0, "角色名称已存在");
        Assert.isTrue(sysRoleMapper.selectCountByQuery(QueryWrapper.create().eq("code", form.getCode())) == 0, "角色编码已存在");
        SysRole sysRole = sysRoleConverter.toEntity(form);
        sysRole.setId(UUID.randomUUID().toString());
        sysRoleMapper.insert(sysRole);

    }

    @Override
    @Transactional
    public void update(RoleForm form) {
        Assert.isTrue(sysRoleMapper.selectCountByQuery(QueryWrapper.create().eq("name", form.getName()).ne("id", form.getId())) == 0, "角色名称已存在");
        Assert.isTrue(sysRoleMapper.selectCountByQuery(QueryWrapper.create().eq("code", form.getCode()).ne("id", form.getId())) == 0, "角色编码已存在");
        SysRole sysRole = sysRoleConverter.toEntity(form);
        sysRoleMapper.update(sysRole);
//        QueryWrapper wrapper = QueryWrapper.create().eq("role_id", sysRole.getId());
//        sysRolePermissionMapper.deleteByQuery(wrapper);
    }

    @Override
    @Transactional
    public void delete(List<String> ids) {
        sysRoleMapper.deleteBatchByIds(ids);
        QueryWrapper wrapper = QueryWrapper.create().in("role_id", ids);
        sysRolePermissionMapper.deleteByQuery(wrapper);
    }

    @Override
    public PageVo<RoleVO> page(RoleQuery query) {
        QueryWrapper wrapper = QueryWrapper.create().like("name", query.getName());
        Page<SysRole> page = sysRoleMapper.paginate(query.getPageNum(), query.getPageSize(), wrapper);
        PageVo<SysRole> pageVo = new PageVo<>();
        pageVo.setList(page.getRecords());
        pageVo.setTotal(page.getTotalRow());
        return sysRoleConverter.toPageVo(pageVo);
    }

    @Override
    public RoleForm form(String id) {
        SysRole role = sysRoleMapper.selectOneById(id);
        Assert.notNull(role ,"角色不存在");
        return sysRoleConverter.toForm(role);
    }

    @Override
    public List<String> getRolePermIds(String roleId) {
        QueryWrapper wrapper = QueryWrapper.create().eq("role_id", roleId).select("permission_id");
        List<SysRolePermission> rolePermissions = sysRolePermissionMapper.selectListByQuery(wrapper);
        return rolePermissions.stream().map(SysRolePermission::getPermissionId).collect(Collectors.toList());
    }

    @Override
    @Transactional
    public void updateRolePerms(RolePermForm form) {
        String roleId = form.getRoleId();
        List<String> perms = form.getPerms();
        SysRole role = sysRoleMapper.selectOneById(roleId);
        Assert.notNull(role, "角色不存在");
        sysRolePermissionMapper.deleteByQuery(QueryWrapper.create().eq("role_id", roleId));

        if (CollectionUtil.isNotEmpty(perms)) {
            List<SysRolePermission> rolePermissions = new ArrayList<>();
            for (String permId : perms) {
                SysRolePermission rolePermission = new SysRolePermission();
                rolePermission.setId(UUID.randomUUID().toString());
                rolePermission.setRoleId(roleId);
                rolePermission.setPermissionId(permId);
                rolePermissions.add(rolePermission);
            }
            sysRolePermissionMapper.insertBatch(rolePermissions);
        }
    }

    @Override
    public List<OptionVO<String>> options(RoleQuery query) {
        QueryWrapper wrapper = QueryWrapper.create().select("id", "name");
        List<SysRole> sysRoles = sysRoleMapper.selectListByQuery(wrapper);
        return sysRoles.stream().map(role -> new OptionVO<>(role.getId(), role.getName())).collect(Collectors.toList());
    }

    @Override
    public Set<String> getRolePermissions(Set<String> roleIds) {
        QueryWrapper wrapper = QueryWrapper.create().in("role_id", roleIds).select("permission_id");
        List<SysRolePermission> rolePermissions = sysRolePermissionMapper.selectListByQuery(wrapper);
        if (rolePermissions.isEmpty()) {
            return Collections.emptySet();
        }
        Set<String> permissionIds = rolePermissions.stream().map(SysRolePermission::getPermissionId).collect(Collectors.toSet());
        wrapper = QueryWrapper.create().in("id", permissionIds).select("id", "perm");
        List<SysPermission> sysPermissions = sysPermissionMapper.selectListByQuery(wrapper);
        Set<String> perms = new HashSet<>();
        for (SysPermission sysPermission : sysPermissions) {
            perms.add(sysPermission.getPerm());
        }
        return perms;
    }

    @Override
    public List<RouteVO> getRoleRoutes(Set<String> roleIds) {
        if (CollectionUtil.isEmpty(roleIds)) {
            return Collections.emptyList();
        }
        QueryWrapper wrapper = QueryWrapper.create().in("role_id", roleIds);
        List<SysRolePermission> rolePermissions = sysRolePermissionMapper.selectListByQuery(wrapper);
        List<String> permissionIds = rolePermissions.stream().map(SysRolePermission::getPermissionId).toList();
        if (CollectionUtil.isEmpty(permissionIds)) {
            return Collections.emptyList();
        }
        wrapper = QueryWrapper.create().in("id", permissionIds).ne("type", MenuTypeEnum.BUTTON.getValue());
        List<SysPermission> permissions = new ArrayList<>(sysPermissionMapper.selectListByQuery(wrapper));

        return buildRoutes(SystemConstants.ROOT_NODE, permissions);
    }


    /**
     * 递归生成菜单路由层级列表
     *
     * @param parentId 父级ID
     * @param menuList 菜单列表
     * @return 路由层级列表
     */
    private List<RouteVO> buildRoutes(String parentId, List<SysPermission> menuList) {
        List<RouteVO> routeList = new ArrayList<>();

        for (SysPermission perm : menuList) {
            if (perm.getPid().equals(parentId)) {
                RouteVO routeVO = toRouteVo(perm);
                List<RouteVO> children = buildRoutes(perm.getId(), menuList);
                if (!children.isEmpty()) {
                    routeVO.setChildren(children);
                }
                routeList.add(routeVO);
            }
        }

        return routeList;
    }

    /**
     * 根据RouteBO创建RouteVo
     */
    private RouteVO toRouteVo(SysPermission menu) {
        RouteVO routeVo = new RouteVO();
        // 获取路由名称
        String routeName = menu.getRouteName();
        if (StrUtil.isBlank(routeName)) {
            // 路由 name 需要驼峰，首字母大写
            routeName = StringUtils.capitalize(StrUtil.toCamelCase(menu.getRoutePath(), '-'));
        }
        // 根据name路由跳转 this.$router.push({name:xxx})
        routeVo.setName(routeName);

        // 根据path路由跳转 this.$router.push({path:xxx})
        routeVo.setPath(menu.getRoutePath());
        routeVo.setRedirect(menu.getRedirect());
        routeVo.setComponent(menu.getComponent());

        RouteVO.Meta meta = new RouteVO.Meta();
        meta.setTitle(menu.getName());
        meta.setIcon(menu.getIcon());
        meta.setHidden(StatusEnum.DISABLE.getValue().equals(menu.getVisible()));
        // 【菜单】是否开启页面缓存
        if (MenuTypeEnum.MENU.getValue().equals(menu.getType())
                && ObjectUtil.equals(menu.getKeepalive(), 1)) {
            meta.setKeepAlive(true);
        }
        meta.setAlwaysShow(ObjectUtil.equals(menu.getAlwaysShow(), 1));

        String paramsJson = menu.getParams();
        // 将 JSON 字符串转换为 Map<String, String>
        if (StrUtil.isNotBlank(paramsJson)) {
            ObjectMapper objectMapper = new ObjectMapper();
            try {
                Map<String, String> paramMap = objectMapper.readValue(paramsJson, new TypeReference<>() {
                });
                meta.setParams(paramMap);
            } catch (Exception e) {
                throw new RuntimeException("解析参数失败", e);
            }
        }
        routeVo.setMeta(meta);
        return routeVo;
    }


}
